// mqttClient.js
const mqtt = require('mqtt');
const mysqlUtil = require('./mysqlUtil');
const config = require('../config'); // 引入配置文件

const mqttHost = config.mqtt.host;
const mqttPort = config.mqtt.port;
const mqttUrl = `mqtt://${mqttHost}:${mqttPort}`;
const mqttOptions = {
    clientId: 'access-control-server',
    clean: true,
    connectTimeout: 4000,
    reconnectPeriod: 1000,
};

const client = mqtt.connect(mqttUrl, mqttOptions);
const doorStatusResponses = {};

client.on('connect', async () => {
    console.log('MQTT客户端已连接');

});

client.on('error', (err) => {
    console.error('MQTT连接失败:', err);
});

client.on('message', async (topic, message) => {
    const messageStr = message.toString();
    console.log('收到MQTT消息:', topic, messageStr);
    const match = topic.match(/devicesend\/(\w+)/);
    if (match) {
        const doorId = match[1];
        console.log('收到门状态响应:', doorId);
        const statusResponse = doorStatusResponses[doorId];
        const messageObj = JSON.parse(messageStr);

        const sql = 'UPDATE device_operations SET operation_result = ? WHERE id = ?';
        if (statusResponse) {
            try {
                if (messageObj.state === 'ok') {
                    const params = [true, messageObj.id];
                    await mysqlUtil.update(sql, params);
                    statusResponse.resolve('成功');
                } else {
                    const params = [false, messageObj.id];
                    await mysqlUtil.update(sql, params);
                    statusResponse.reject(new Error('失败'));
                }
            } catch (error) {
                console.error('更新操作记录失败:', error.message);
                statusResponse.reject(new Error('更新操作记录失败'));
            } finally {
                client.unsubscribe(topic); // 取消订阅
                delete doorStatusResponses[doorId]; // 删除Promise
            }
        }
    }
});

function openDoor(doorId,user) {
    return new Promise(async (resolve, reject) => {
        const topic = `/deviceaccept/${doorId}`;
        const qos = 0;
        const statusTopic = `/devicesend/${doorId}`;

        const sql = 'INSERT INTO device_operations (device_code, operation_type, operation_time, create_user) VALUES (?, ?, ?, ?)';
        const params = [doorId, 'open', new Date(), user.id];
        let insertId;
        try {
            insertId = await mysqlUtil.insert(sql, params);
            console.log('增加操作记录:', insertId);
        } catch (error) {
            console.error('增加操作记录失败:', error.message);
            reject(new Error('增加操作记录失败'));
            return;
        }

        doorStatusResponses[doorId] = { resolve, reject };

        // 设置超时，防止无限等待
        const timeoutId = setTimeout(() => {
            if (doorStatusResponses[doorId]) {
                const sql1 = 'UPDATE device_operations SET operation_result = ? WHERE id = ?';
                const params1 = [false, insertId];
                mysqlUtil.update(sql1, params1)
                    .then(() => {
                        reject(new Error('开门操作超时'));
                    })
                    .catch(err => {
                        console.error('更新操作记录失败:', err.message);
                        reject(new Error('更新操作记录失败'));
                    })
                    .finally(() => {
                        client.unsubscribe(statusTopic); // 取消订阅
                        delete doorStatusResponses[doorId]; // 删除Promise
                    });
            }
        }, 5000); // 5秒超时

        client.subscribe(statusTopic, (err) => {
            if (err) {
                console.error('订阅主题失败:', err);
                clearTimeout(timeoutId);
                reject(new Error('订阅门状态失败'));
                return;
            }

            const content = JSON.stringify({
                action: "Crldoor",
                state: 'open',
                holdopen: 0,
                id: insertId,
            });
            client.publish(topic, content, { qos }, (err) => {
                if (err) {
                    console.error('发布消息失败:', err);
                    clearTimeout(timeoutId);
                    client.unsubscribe(statusTopic); // 取消订阅
                    reject(new Error('开门失败'));
                }
            });
        });
    });
}

module.exports = {
    openDoor,
};